package com.xhj.ipersistent.mapping;

import com.xhj.ipersistent.parsing.GenericTokenParser;
import com.xhj.ipersistent.parsing.ParameterMappingTokenHandler;

/**
 * MappedStatement
 *
 * @author XJks
 * @description 映射配置类，存放自定义实体类mapper.xml的解析内容
 */
public class MappedStatement {
    /**
     * TODO:
     *  唯一标识，格式:namespace.id，比如:com.xhj.ipersistent.dao.IUserDao.selectById
     *  namespace:对应mapper.xml文件中根标签<mapper namespace="com.xhj.ipersistent.dao.IUserDao"><mapper/>中的namespace属性值
     *  id:对应mapper.xml文件中具体的sql标签<select id="selectById"></select>中的id属性值
     */
    private String statementId;

    /**
     * TODO:
     *  返回值类型:对应mapper.xml文件中具体的sql标签<select id="selectById" resultType="com.xhj.entity.User"></select>中的resultType属性值
     */
    private String resultType;

    /**
     * TODO:
     *  参数类型:对应mapper.xml文件中具体的sql标签<select id="selectById" parameterType="com.xhj.entity.User"></select>中的parameterType属性值
     */
    private String parameterType;

    /**
     * TODO:
     *  sql语句:对应mapper.xml文件中具体的sql标签<select id="selectById">select * from user where id = #{id}</select>中的标签体内容，即具体的未解析的sql语句，包含#{}占位符
     */
    private String sql;

    /**
     * TODO:
     *  sql语句类型:对应mapper.xml文件中具体的sql标签<select>、<insert>、<update>、<delete>中的标签名称，即sql语句的类型，可能的值有:select、insert、update、delete，分别对应查询、插入、更新、删除操作。
     *  为对应Dao接口生成动态代理对象后，调用具体方法时，框架会根据方法名找到对应的MappedStatement对象，然后通过sqlCommandType属性判断执行哪种类型的SQL操作。
     */
    private String sqlCommandType;

    private BoundSql boundSql;

    public MappedStatement() {
    }

    public String getStatementId() {
        return statementId;
    }

    public void setStatementId(String statementId) {
        this.statementId = statementId;
    }

    public String getResultType() {
        return resultType;
    }

    public void setResultType(String resultType) {
        this.resultType = resultType;
    }

    public String getParameterType() {
        return parameterType;
    }

    public void setParameterType(String parameterType) {
        this.parameterType = parameterType;
    }

    public String getSql() {
        return sql;
    }

    public void setSql(String sql) {
        this.sql = sql;
    }

    public String getSqlCommandType() {
        return sqlCommandType;
    }

    public void setSqlCommandType(String sqlCommandType) {
        this.sqlCommandType = sqlCommandType;
    }

    public BoundSql getBoundSql() {
        return boundSql;
    }

    /**
     * TODO:使用ParameterMappingTokenHandler和GenericTokenParser对sql语句进行解析，得到解析后的sql语句和参数映射列表，并封装到BoundSql对象中
     */
    public void initBoundSql() {
        // 创建参数映射令牌处理器
        ParameterMappingTokenHandler parameterMappingTokenHandler = new ParameterMappingTokenHandler();
        // 创建通用令牌解析器，解析#{}占位符
        GenericTokenParser genericTokenParser = new GenericTokenParser("#{", "}", parameterMappingTokenHandler);
        // 解析sql语句，得到最终的sql语句和参数映射列表，并封装到BoundSql对象中
        String finalSql = genericTokenParser.parse(this.sql);
        this.boundSql = new BoundSql(finalSql, parameterMappingTokenHandler.getParameterMappingList());
    }
}
